#pragma once
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif // !WIN32_LEAN_AND_MEAN
#include <common_header.h>
#include <dxgi1_6.h>
#include <d3d12.h>
#include <wrl.h>

#ifdef _DEBUG
#define DXASSERT(x) assert((x) == S_OK)
#else
#define DXASSERT(x) x
#endif // _DEBUG

#define DXUPALIGN(A,B) ((((A)+((B)-1))&~((B)-1)))

#define DXCONSTANTALIGN(A) DXUPALIGN(A,D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT)

#define IIDPPV(x) primal::gfx::get_guid((x)),((void**)(x).GetAddressOf())

#define DXUUID(x) primal::gfx::get_guid((x)),((void**)(&x))

namespace primal
{
	namespace gfx
	{
		using Microsoft::WRL::ComPtr;

		template<typename T>
		class GetComPtr
		{
		public:
			T* ptr()
			{
				return (T*)this;
			}
		};

		using ID3D12DeviceN = ID3D12Device7;
		using ID3D12GraphicsCommandListN = ID3D12GraphicsCommandList6;
		using IDXGIFactoryN = IDXGIFactory7;
		using IDXGISwapChainN = IDXGISwapChain4;
		using IDXGIAdapterN = IDXGIAdapter4;

		template<typename T>
		constexpr GUID get_guid(const ComPtr<T>& t)
		{
			return __uuidof(T);
		}

		template<typename T>
		constexpr GUID get_guid(T* t)
		{
			return __uuidof(T);
		}

		template<typename T>
		inline void release(T*& obj)
		{
			if (obj != nullptr)
			{
				obj->Release();
				obj = nullptr;
			}
		}

		struct descriptor_handle
		{
			D3D12_CPU_DESCRIPTOR_HANDLE cpu;
			D3D12_GPU_DESCRIPTOR_HANDLE gpu;
		};

		template<typename T>
		u64 get_constant_alignment_size()
		{
			static u64 align_size{ DXCONSTANTALIGN(sizeof(T)) };
			return align_size;
		}



		constexpr u32 COMMAND_FRAME_COUNT{ 8u };
	}
}